import 'dart:async';

import 'package:dio/dio.dart';
import 'package:flutter_enjoy_plus/constants/index.dart';
import 'package:flutter_enjoy_plus/utils/EvenBus.dart';
import 'package:flutter_enjoy_plus/utils/PromptAction.dart';
import 'package:flutter_enjoy_plus/utils/TokenManager.dart';

class _RequestDio {
  final Dio _dio = Dio();

  _RequestDio() {
    // 配置基地址 和 超时时间
    _dio.options.baseUrl = GlobalVariable.BASE_URL;
    _dio.options.connectTimeout =
        const Duration(seconds: GlobalVariable.TIME_OUT);
    _dio.options.receiveTimeout =
        const Duration(seconds: GlobalVariable.TIME_OUT);
    // 配置拦截器
    _setinterceptors();
  }
  Future get(String url, {Map<String, dynamic>? params}) async {
    final res = await _dio.get(url, queryParameters: params);
    return _handleResponse(res);
  }

  Future post(String url, {Map<String, dynamic>? data}) async {
    final res = await _dio.post(url, data: data);
    return _handleResponse(res);
  }

  // 上传图片
  Future upload(String url, {FormData? data}) async {
    final res = await _dio.post(url, data: data);
    return _handleResponse(res);
  }

  Future put(String url, {Map<String, dynamic>? data}) async {
    final res = await _dio.put(url, data: data);
    return _handleResponse(res);
  }

  Future delete(String url, {Map<String, dynamic>? data}) async {
    final res = await _dio.delete(url, data: data);
    return _handleResponse(res);
  }

  // 针对请求的返回结果处理 -- 针对的是业务结果 与 响应拦截器不同
  _handleResponse(Response response) {
    if (response.data['code'] == GlobalVariable.SUCCEED_CODE) {
      return response.data['data'];
    } else {
      // 提示用户
      Promptaction.showError(response.data['message']);
      // 抛出异常
      throw Exception(response.data['message']);
    }
  }

  // 判断refershToken是否过期
  Future<bool> _isRefreshTokenExpired(String refreshToken) async {
    Dio dio = Dio();
    try {
      final res = await dio.post(
          '${GlobalVariable.BASE_URL}${HTTP_PATH.REFRESH_TOKEN}',
          options: Options(headers: {"Authorization": 'Bearer $refreshToken'}));
      if (res.data['code'] == 10000) {
        tokenManager.setToken(
          res.data['data']['token'],
          refreshToken: res.data['data']['refreshToken'],
        );
        return true;
      } else {
        return false;
      }
    } catch (e) {
      return false;
    }
  }

  // 拦截器
  _setinterceptors() {
    _dio.interceptors.add(
      InterceptorsWrapper(
        onRequest: (RequestOptions options, RequestInterceptorHandler handler) {
          // 如果你想完成请求并返回一些自定义数据，你可以使用 `handler.resolve(response)`。
          // 如果你想终止请求并触发一个错误，你可以使用 `handler.reject(error)`。
          // 统一携带token
          String token = tokenManager.getToken();
          if (token.isNotEmpty) {
            options.headers['Authorization'] = 'Bearer $token';
          }
          return handler.next(options);
        },
        onResponse: (Response response, ResponseInterceptorHandler handler) {
          // 如果你想终止请求并触发一个错误，你可以使用 `handler.reject(error)`。
          if (response.statusCode! >= 200 && response.statusCode! < 300) {
            // 请求成功了
            return handler.next(response);
          } else {
            // 请求失败了
            // 针对不同的情况码处理
            Promptaction.showError(response.statusMessage!);
            handler
                .reject(DioException(requestOptions: response.requestOptions));
          }
        },
        onError: (DioException error, ErrorInterceptorHandler handler) async {
          // 如果你想完成请求并返回一些自定义数据，你可以使用 `handler.resolve(response)`。
          if (error.response?.statusCode == 401) {
            // 获取refreshToken
            String refreshToken = tokenManager.getRefreshToken();
            if (refreshToken.isNotEmpty) {
              // 判断refreshToken是否过期
              bool isOk = await _isRefreshTokenExpired(refreshToken);
              if (isOk) {
                // refreshToken有效 并且已经将最新的token 和 refreshToken 存储到本地
                // 重新发起之前失败的请求
                // eventBus.fire(LoginEvent());

                final res = await _dio.fetch(error.requestOptions);
                handler.resolve(res);
              } else {
                // refreshToken过期
                // 删除token
                tokenManager.removeToken();
                // 由于不是在组件中不能使用上下文对象，需要使用eventBus
                eventBus.fire(LogoutEvent());
              }
            } else {
              // 删除token
              tokenManager.removeToken();
              // 由于不是在组件中不能使用上下文对象，需要使用eventBus
              eventBus.fire(LogoutEvent());
            }
          }
          return handler.next(error);
        },
      ),
    );
  }
}

final requestDio = _RequestDio();
